/**
 * 所有版权归 广西梧州 陈锦韬 所有
 *
 * @Title: SingleDetailHandlerContainer
 * @Package com.rx.core.mode
 * @Description: 单表详情处理器
 * @author: 陈锦韬
 * @date: 2021\6\11 0011
 * @version V1.0
 * @Copyright: 2021 陈锦韬  All rights reserved.
 */
package com.rx.core.mode;

import com.rx.core.base.RxBaseConstant;
import com.rx.core.bean.RxConfigForHandler;
import com.rx.core.enm.HANDLER_TYPE;
import com.rx.core.enm.RESULT_CODE;
import com.rx.core.enm.RX_LOG_MODE;
import com.rx.core.handler.RxHandler;
import com.rx.core.handler.RxHandlerAfter;
import com.rx.core.handler.RxHandlerPrev;
import com.rx.core.handler.RxHandlerWraper;
import com.rx.core.util.EmptyChecker;
import com.rx.core.util.RxSpecialUtil;
import com.rx.core.util.RxUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * @author: Administrator
 * @Description: 处理器总容器
 * @date: 2021\6\11 0011
 */
@Component
@Slf4j
public class TotalHandlerContainer extends HandlerContainer{
    /**
     * 处理器容器
     */
    public static Map<String, RxHandlerWraper> container = new HashMap<>();
    public static Map<String, RxHandlerWraper> containerPrev = new HashMap<>();
    public static Map<String, RxHandlerWraper> containerAfter = new HashMap<>();

    public static RxHandlerWraper getHandlerByClass(Class cls,String key){
        try {
            return (RxHandlerWraper) RxSpecialUtil.AnnoForHandler(cls,
                    ()->getPrevHandler(key),
                    ()->getHandler(key),
                    ()->getAfterHandler(key));
        } catch (Throwable throwable) {
            return null;
        }
    }
    public static RxHandlerWraper getPrevHandler(String key){
        return containerPrev.get(key);
    }
    public static RxHandlerWraper getHandler(String key){
        return container.get(key);
    }
    public static RxHandlerWraper getAfterHandler(String key){
        return containerAfter.get(key);
    }

    public static void setHandler( Class cls,RxHandlerWraper handlerWraper){
        if (cls == RxHandlerPrev.class){
            containerPrev.put(handlerWraper.getHandleName(),handlerWraper);
        }else if (cls == RxHandlerAfter.class){
            containerAfter.put(handlerWraper.getHandleName(),handlerWraper);
        }else if (cls == RxHandler.class){
            container.put(handlerWraper.getHandleName(),handlerWraper);
        }else {
            RxUtil.CheckUtil.throwOut(RESULT_CODE.FAIL);
        }
    }

    private static StringBuilder logHandle(RxHandlerWraper handlerWraper) {
        StringBuilder sb = new StringBuilder();
        for (HANDLER_TYPE handlerType : handlerWraper.handlerTypes()) {
            sb.append("  模式：").append(handlerType.getValue()).append("\n");
            log.info(RX_LOG_MODE.HANDLER_INFO.getFormat("  模式：{}"), handlerType.getValue());
            List<String> urlList = handlerWraper.handlerType(handlerType);
            StringBuilder stringBuilder = new StringBuilder();
            for (String url : urlList) {
                stringBuilder.append("{")
                        .append(url)
                        .append(" > 优先级: ")
                        .append(handlerWraper.order(url))
                        .append("} ");
            }
            log.info(RX_LOG_MODE.HANDLER_INFO.getFormat("  URL：{}"), stringBuilder.toString());
            sb.append("   URL:").append(stringBuilder).append("\n");
        }
        return sb;
    }
    /**
     * 打印当前所有处理器情况。
     */
    public static StringBuilder log(){
        log.info(RX_LOG_MODE.HANDLER_INFO.getFormat("*****************************************"));
        log.info(RX_LOG_MODE.DEFAULT.getFormat(),"前处理器");
        StringBuilder sb = new StringBuilder("前处理器\n");
        for (Map.Entry<String, RxHandlerWraper> stringRxHandlerWraperEntry : containerPrev.entrySet()) {
            log.info(RX_LOG_MODE.DEFAULT.getFormat("名称：{}"),"前处理器",stringRxHandlerWraperEntry.getKey());
            sb.append("名称：").append(stringRxHandlerWraperEntry.getKey()).append("\n");
            StringBuilder tmp = logHandle(stringRxHandlerWraperEntry.getValue());
            sb.append(tmp);
        }
        log.info("");
        log.info(RX_LOG_MODE.DEFAULT.getFormat(),"覆盖处理器");
        sb.append("覆盖处理器\n");
        for (Map.Entry<String, RxHandlerWraper> stringRxHandlerWraperEntry : container.entrySet()) {
            log.info(RX_LOG_MODE.DEFAULT.getFormat("名称：{}"),"覆盖处理器",stringRxHandlerWraperEntry.getKey());
            sb.append("名称：").append(stringRxHandlerWraperEntry.getKey()).append("\n");
            StringBuilder tmp = logHandle(stringRxHandlerWraperEntry.getValue());
            sb.append(tmp);
        }
        log.info("");
        log.info(RX_LOG_MODE.DEFAULT.getFormat(),"后处理器");
        sb.append("后处理器\n");
        for (Map.Entry<String, RxHandlerWraper> stringRxHandlerWraperEntry : containerAfter.entrySet()) {
            log.info(RX_LOG_MODE.DEFAULT.getFormat("名称：{}"),"后处理器",stringRxHandlerWraperEntry.getKey());
            StringBuilder tmp = logHandle(stringRxHandlerWraperEntry.getValue());
            sb.append(tmp);
        }
        log.info(RX_LOG_MODE.HANDLER_INFO.getFormat("*****************************************"));
        return sb;
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * 配置
     */
    @Autowired
    RxConfigForHandler config;

    /**
     * 初始化
     */
    @PostConstruct
    public void initialize() {
        log.info("springboot 启动完成\n");
        log.info(RX_LOG_MODE.DEFAULT.getFormat(),"根据配置文件对处理器进行匹配");
        // 前处理器
        setHandlerByConfig(config.getPrev(),RxHandlerPrev.class);
        // 覆盖处理器
        setHandlerByConfig(config.getOver(),RxHandler.class);
        // 后处理器
        setHandlerByConfig(config.getAfter(),RxHandlerAfter.class);

        log();
    }
    private void setHandlerByConfig(List<RxConfigForHandler.RxConfigHandlerBean> configList, Class anno){
        for (Object object : RxUtil.ListUtil.notNullList(configList)) {
            setHandlerByConfig((RxConfigForHandler.RxConfigHandlerBean)object,anno);
        }
    }
    private void doByTypeAndUrl(RxConfigForHandler.RxConfigHandlerBean configHandlerBean,appendOrRemove appendOrRemove){
        List<HANDLER_TYPE> typeList = configHandlerBean.getEnumHandlerTypeList();
        if(EmptyChecker.isEmpty(typeList)){
            List<HANDLER_TYPE> exTypeList = configHandlerBean.getExHandlerTypeList();
            if(EmptyChecker.isEmpty(exTypeList)){
                // TYPE,EXTYPE为空。则认为是ALL
                typeList = new ArrayList<>();
                typeList.add(HANDLER_TYPE.ALL);
            }else {
                // 只有在type 失效的情况下 exType 才有效
                typeList = exTypeList;
            }
        }

        for (HANDLER_TYPE handlerType : typeList) {
            for (String url : configHandlerBean.getUrlList()) {
                // URL
                if (RxBaseConstant.DEFAULT_URL_KEY.equalsIgnoreCase(url)){
                    continue;
                }
                appendOrRemove.done(new appendOrRemoveParam(
                        url,
                        handlerType,
                        configHandlerBean.dealOrder()
                        ));
            }
            for (String url : configHandlerBean.getExUrlList()) {
                // 排除url 设置
                if (RxBaseConstant.DEFAULT_URL_KEY.equalsIgnoreCase(url)){
                    continue;
                }
                appendOrRemove.done(new appendOrRemoveParam(
                        EXT_PREFIX + url,
                        handlerType,
                        configHandlerBean.dealOrder()
                ));
            }
            if (EmptyChecker.isEmpty(configHandlerBean.getUrlList())&&EmptyChecker.isEmpty(configHandlerBean.getExUrlList())){
                // 没有设置url 则所有请求都需要
                appendOrRemove.done(new appendOrRemoveParam(
                        ALL_PREFIX,
                        handlerType,
                        configHandlerBean.dealOrder()
                ));
            }
        }
    }
    private void setHandlerByConfig(RxConfigForHandler.RxConfigHandlerBean configHandlerBean,Class anno){

        if (configHandlerBean.noName()){
            return;
        }
        String name = HandlerContainer.getHandlerName(configHandlerBean.getName());
        RxHandlerWraper rxHandlerWraper = getHandlerByClass(anno,name);
        if (EmptyChecker.isEmpty(rxHandlerWraper)){
            log.warn(RX_LOG_MODE.ERROR.getFormat("配置错误，处理器【{}】不存在"),name);
            return;
        }

        if (configHandlerBean.yesStop()){
            doByTypeAndUrl(configHandlerBean,e->{
                rxHandlerWraper.removeOrder(e.getUrl());
                rxHandlerWraper.removeHandlerType(e.getType(),e.getUrl());
                removeHandlerByConfig(rxHandlerWraper,e.getUrl(),e.getType(),anno);
            });
            return;
        }

        doByTypeAndUrl(configHandlerBean,e->{
            rxHandlerWraper.order(e.getUrl(),e.getOrder());
            setHandlerByConfig(rxHandlerWraper,e.getUrl(),e.getType(),anno);
        });
    }

    /**
     * 设置处理器
     * @param rxHandlerWraper
     * @param url
     * @param type
     * @param anno
     * @return
     */
    private boolean setHandlerByConfig(RxHandlerWraper rxHandlerWraper,String url,HANDLER_TYPE type,Class anno){
        if (hasExist(rxHandlerWraper.getHandleName(),url,type,anno)){
            // 存在不改变。或只改变order
            return true;
        }
        type.memmory().setHandler(url,anno,rxHandlerWraper);
        return false;
    }

    private boolean removeHandlerByConfig(RxHandlerWraper rxHandlerWraper,String url,HANDLER_TYPE type,Class anno){
        type.memmory().remove(url,anno,rxHandlerWraper);
        return false;
    }

    /**
     * 相关容器是否存在处理器
     * @param name
     * @param url
     * @param type
     * @param cls
     * @return
     */
    private boolean hasExist(String name,String url,HANDLER_TYPE type,Class cls){
        List<RxHandlerWraper> handlerWraperList = getHandlerListByAnno(url,type,cls);
        for (RxHandlerWraper handlerWraper : handlerWraperList) {
            if (handlerWraper.getHandleName().equalsIgnoreCase(name)){
                // 存在不管。
                return true;
            }
        }
        return false;
    }

    /**
     * 获取容器函数
     * @param url
     * @param type
     * @param anno
     * @return
     */
    private List<RxHandlerWraper> getHandlerListByAnno(String url,HANDLER_TYPE type,Class anno){
        try {
            return type.getHandlerListByAnno(url,anno);
        } catch (Throwable throwable) {
            log.error(RX_LOG_MODE.DEFAULT.getFormat(),"获取处理器失败：{}",throwable.getMessage());
            return Collections.emptyList();
        }
    }



}
